<?php

namespace common\service\step_category_month_report;

use common\model\StepCategoryMonthReportModel;

abstract class EpisodeReportCountBase
{
    /** @var StepCategoryMonthCountObject $countObject */
    protected $countObject;

    /**
     * 检查数据是否已经固化过,固化过的数据直接返回
     * @param $projectId
     * @param $monthStart
     * @param $stepCategoryIdList
     * @return bool
     */
    public function checkDataStored($projectId, $stepCategoryIdList, $monthStart)
    {
        $monthStart = strtotime($monthStart);
        $stepCategoryMonthReport = model(StepCategoryMonthReportModel::class)
            ->where([
                'project_id' => $projectId,
                'step_category_id' => ['IN', implode(',', $stepCategoryIdList)],
                'month_time' => $monthStart,
            ])
            ->find();
        if (empty($stepCategoryMonthReport)) {
            return false;
        }
        $this->countObject = new StepCategoryMonthCountObject();
        $this->countObject->projectId = $projectId;
        $this->countObject->tenantId = $stepCategoryMonthReport['tenant_id'];
        $this->countObject->monthTime = $monthStart;
        $this->countObject->planDelivery = $stepCategoryMonthReport['plan_delivery'];
        $this->countObject->addDelivery = $stepCategoryMonthReport['add_delivery'];
        $this->countObject->shouldDelivery = $this->countObject->planDelivery + $this->countObject->addDelivery;
        $this->countObject->delivery = $stepCategoryMonthReport['delivery'];
        $this->countObject->abnormal = $stepCategoryMonthReport['abnormal'];
        $this->countObject->deliveryNoRepair = $stepCategoryMonthReport['delivery_no_repair'];
        $this->countObject->deliveryUnit = $stepCategoryMonthReport['delivery_unit'];
        if ($this->countObject->shouldDelivery != 0) {
            $this->countObject->deliveryPercent = $this->countObject->delivery / $this->countObject->shouldDelivery;
        }
        if ($this->countObject->delivery != 0) {
            $this->countObject->passPercent = $this->countObject->deliveryNoRepair / $this->countObject->delivery;
        }
        if ($stepCategoryMonthReport['work_order_number'] != 0) {
            $this->countObject->taskWorkOrderPercent = $stepCategoryMonthReport['current_work_order_number'] / $stepCategoryMonthReport['work_order_number'];
        }
        $this->countObject->havePlan = $stepCategoryMonthReport['have_plan'] === 'yes';
        $this->countObject->isPlanDone = $stepCategoryMonthReport['is_plan_done'] === 'yes';

        return true;
    }

    /**
     * 查询详情数据
     * @param $projectId
     * @param $stepCategoryIdList
     * @param $startMonth
     * @param null $endMonth
     * @param bool $needHistory
     * @return void
     */
    public function getData($projectId, $stepCategoryIdList, $startMonth, $endMonth = null, $needHistory = false)
    {
        if (!empty($endMonth) || !$this->checkDataStored($projectId, $stepCategoryIdList, $startMonth)) {
            $this->calculate($projectId, $stepCategoryIdList, $startMonth, $endMonth);
        }

        if (empty($endMonth) && $needHistory) {
            $monthStart = strtotime($startMonth);
            $historyMonth = [];
            $historyMonthLength = 2;
            for ($i = $historyMonthLength; $i >= 1; $i--) {
                $historyMonth[] = date("Y-m", strtotime("-{$i} month", $monthStart));
            }
            $this->appendHistoryData($projectId, $historyMonth, $stepCategoryIdList);
            $this->countObject->passPercentHistory[] = [
                'date' => $startMonth,
                'value' => $this->countObject->passPercent,
            ];
            $this->countObject->deliveryPercentHistory[] = [
                'date' => $startMonth,
                'value' => $this->countObject->deliveryPercent,
            ];
            $this->countObject->taskWorkOrderPercentHistory[] = [
                'date' => $startMonth,
                'value' => $this->countObject->taskWorkOrderPercent,
            ];
            $this->countObject->deliveryHistory[] = [
                'date' => $startMonth,
                'value' => $this->countObject->delivery,
            ];
        }
    }

    /**
     *
     * @param $projectId
     * @param $stepCategoryIdList
     * @param $monthStart
     * @param $monthEnd
     * @return void
     */
    abstract public function calculate($projectId, $stepCategoryIdList, $monthStart, $monthEnd = null);

    /**
     * 查询计划完成的计划数据
     * @param $projectId
     * @param $monthStart
     * @param $monthEnd
     * @param $stepCategoryIdList
     * @return array
     */
    abstract public function getPlanDonePlanData($projectId, $monthStart, $monthEnd, $stepCategoryIdList);

    /**
     * 是否有计划
     * @return bool
     */
    public function getHavePlan()
    {
        return $this->countObject->havePlan;
    }

    /**
     * 查询计划交付
     * @return int
     */
    public function getPlanDelivery()
    {
        return $this->countObject->planDelivery;
    }

    /**
     * 查询新增交付
     * @return int
     */
    public function getAddDelivery()
    {
        return $this->countObject->addDelivery;
    }

    /**
     * 查询实际应交付
     * @return int
     */
    public function getShouldDelivery()
    {
        return $this->countObject->shouldDelivery;
    }

    /**
     * 交付数
     * @return int
     */
    public function getDelivery()
    {
        return $this->countObject->delivery;
    }

    /**
     * 交付单位
     * @return string
     */
    public function getDeliveryUnit()
    {
        return $this->countObject->deliveryUnit;
    }

    /**
     * 交付历史
     * @return array
     */
    public function getDeliveryHistory()
    {
        return $this->countObject->deliveryHistory;
    }

    /**
     * 查询未返修交付
     * @return int
     */
    public function getDeliveryNoRepair()
    {
        return $this->countObject->deliveryNoRepair;
    }

    /**
     * 查询异常数量
     * @return int
     */
    public function getAbnormal()
    {
        return $this->countObject->abnormal;
    }

    /**
     * 查询交付率
     * @return float
     */
    public function getDeliveryPercent()
    {
        return $this->countObject->deliveryPercent;
    }

    /**
     * 设置交付率
     * @return void
     */
    public function setDeliveryPercent()
    {
        // 交付率
        if ($this->countObject->planDelivery > 0) {
            $this->countObject->deliveryPercent = $this->countObject->delivery / $this->countObject->planDelivery;
        }
    }

    /**
     * 查询交付率
     * @return array
     */
    public function getDeliveryPercentHistory()
    {
        return $this->countObject->deliveryPercentHistory;
    }

    /**
     * 查询通过率
     * @return float
     */
    public function getPassPercent()
    {
        return $this->countObject->passPercent;
    }

    /**
     * 查询通过率历史
     * @return array
     */
    public function getPassPercentHistory()
    {
        return $this->countObject->passPercentHistory;
    }

    /**
     * 查询问题工单占比
     * @return float
     */
    public function getTaskWorkOrderPercent()
    {
        return $this->countObject->taskWorkOrderPercent;
    }

    /**
     * 问题工单占比历史
     * @return array
     */
    public function getTaskWorkOrderPercentHistory()
    {
        return $this->countObject->taskWorkOrderPercentHistory;
    }

    /**
     * 是否达标
     * @return string
     */
    public function getIsPlanDone()
    {
        return $this->countObject->isPlanDone;
    }

    /**
     * 设置是否达标
     * @return void
     */
    public function setIsPlanDone()
    {
        $this->countObject->isPlanDone = $this->countObject->abnormal == 0;
    }


    /**
     * 追加历史信息
     * @param int $projectId
     * @param array $historyMonth
     * @param array $stepCategoryIdList
     * @return void
     */
    public function appendHistoryData(int $projectId, array $historyMonth, array $stepCategoryIdList)
    {
        // 追加历史
        foreach ($historyMonth as $month) {
            $calculator = new static();
            $calculator->getData($projectId, $stepCategoryIdList, $month, null, false);
            $this->countObject->deliveryPercentHistory[] = [
                'date' => $month,
                'value' => $calculator->getDeliveryPercent(),
            ];
            $this->countObject->passPercentHistory[] = [
                'date' => $month,
                'value' => $calculator->getPassPercent(),
            ];
            $this->countObject->taskWorkOrderPercentHistory[] = [
                'date' => $month,
                'value' => $calculator->getTaskWorkOrderPercent(),
            ];
            $this->countObject->deliveryHistory[] = [
                'date' => $month,
                'value' => $calculator->getDelivery(),
            ];
        }
    }

    /**
     * 保存报表数据
     * @return void
     */
    public function saveCountObjectData()
    {
        if (!$this->countObject->canBeSaved) {
            return;
        }
        $monthStart = strtotime($this->countObject->monthTime);
        $currentMonthStart = strtotime(date("Y-m") . '-01 00:00:00');
        if (APP_DEBUG || $currentMonthStart <= $monthStart) {
            return;
        }
        $stepCategoryReportData = [
            'tenant_id' => $this->countObject->tenantId,
            'project_id' => $this->countObject->projectId,
            'step_category_id' => 0,
            'step_category_ids' => $this->countObject->stepCategoryIds,
            'month_time' => $this->countObject->monthTime,
            'delivery_unit' => $this->countObject->deliveryUnit,
            'plan_delivery' => $this->countObject->planDelivery,
            'add_delivery' => $this->countObject->addDelivery,
            'delivery' => $this->countObject->delivery,
            'delivery_no_repair' => $this->countObject->deliveryNoRepair,
            'abnormal' => $this->countObject->abnormal,
            'current_work_order_number' => $this->countObject->currentWorkOrderNumber,
            'work_order_number' => $this->countObject->workOrderNumber,
            'have_plan' => $this->countObject->havePlan ? 'yes' : 'no',
            'is_plan_done' => $this->countObject->isPlanDone ? 'yes' : 'no',
        ];
        foreach (explode(',', $this->countObject->stepCategoryIds) as $stepCategoryId) {
            $stepCategoryReportData['step_category_id'] = $stepCategoryId;
            model(StepCategoryMonthReportModel::class)->addItem($stepCategoryReportData);
        }
    }
}
